import pandas as pd
from sklearn.metrics import mean_absolute_error
import catboost as cb
import matplotlib.pyplot as plt

# 读取数据
data = pd.read_csv('data.csv')

# 将 time 列转换为 datetime 类型
data['time'] = pd.to_datetime(data['time'])

# 确保数据按时间排序
data = data.sort_values(by='time').reset_index(drop=True)

# 创建一个新的列，存储三分钟前的IC_DCS_CHIMNEY_NOX值
# 注意：这会导致数据的前三行没有对应的“三分钟前”的值，因此我们需要删除这些行
data['IC_DCS_CHIMNEY_NOX_lagged'] = data['IC_DCS_CHIMNEY_NOX'].shift(3)
data = data.dropna()  # 删除包含NaN的行

# 现在IC_DCS_CHIMNEY_NOX_lagged是目标变量
y = data['IC_DCS_CHIMNEY_NOX_lagged']

# 从 time 列中提取分钟（或其他时间特征，如果需要）
# 但注意，这里我们不再直接使用minute作为特征，因为我们已经确保了时间顺序
# 并且将使用整个时间序列来划分训练集和测试集
# X = data[['minute', ...]]  # 如果需要其他时间特征，可以在这里添加
X = data.drop(columns=['IC_DCS_CHIMNEY_NOX', 'IC_DCS_CHIMNEY_NOX_lagged', 'time'])  # 剩余列作为特征

# 基于时间戳划分训练集和测试集
# 我们将使用一个固定的时间点来划分，而不是随机划分
# 假设我们使用最后20%的时间段作为测试集
train_cutoff = data['time'].quantile(0.8)
X_train = X[data['time'] < train_cutoff]
y_train = y[data['time'] < train_cutoff]
X_test = X[data['time'] >= train_cutoff]
y_test = y[data['time'] >= train_cutoff]

# 为了绘制时间序列图，我们需要保留时间戳
time_train = data['time'][data['time'] < train_cutoff]
time_test = data['time'][data['time'] >= train_cutoff]

# 初始化CatBoostRegressor模型
model = cb.CatBoostRegressor(iterations=1500,
                             learning_rate=0.01,
                             depth=4,
                             loss_function='MAE',
                             verbose=False)

# 训练模型
model.fit(X_train, y_train, eval_set=(X_test, y_test), early_stopping_rounds=50)

# 预测测试集
y_pred = model.predict(X_test)

# 计算MAE
mae = mean_absolute_error(y_test, y_pred)
print(f'Mean Absolute Error: {mae}')

# 可视化预测结果（可选）
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, alpha=0.7)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Actual NOx Concentration (3 minutes ago)')
plt.ylabel('Predicted NOx Concentration')
plt.title('Actual vs Predicted NOx Concentration')
plt.show()

# 可视化时间序列图（新增）
plt.figure(figsize=(14, 7))
plt.plot(time_test, y_test, label='Actual NOx Concentration', color='blue', lw=2)
plt.plot(time_test, y_pred, label='Predicted NOx Concentration', color='red', lw=2)
plt.xlabel('Time')
plt.ylabel('NOx Concentration')
plt.title('Time Series of Actual and Predicted NOx Concentration')
plt.legend()
plt.grid(True)
plt.show()

# 可视化特征重要性（可选）
feature_importances = model.get_feature_importance()
feature_names = X.columns
feature_importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': feature_importances})
feature_importance_df = feature_importance_df.sort_values(by='Importance', ascending=False)

plt.figure(figsize=(12, 8))
plt.barh(feature_importance_df['Feature'], feature_importance_df['Importance'])
plt.xlabel('Feature Importance')
plt.ylabel('Feature')
plt.title('Feature Importance for NOx Concentration Prediction')
plt.gca().invert_yaxis()
plt.tight_layout()
plt.show()